package com.kamistoat.meimeichat.meimeichatclient;

import com.kamistoat.meimeichat.meimeichatclient.application.UIServiceConnector;
import com.kamistoat.meimeichat.meimeichatclient.config.NettyClientConstant;
import com.kamistoat.meimeichat.meimeichatclient.event.ChatEvent;
import com.kamistoat.meimeichat.meimeichatclient.event.LoginEvent;
import com.kamistoat.meimeichat.meimeichatclient.infrastructure.util.BeanUtil;
import com.kamistoat.meimeichat.meimeichatclient.infrastructure.util.CacheUtil;
import com.kamistoat.meimeichat.meimeichatclient.kcp.KcpNettyClient;
import com.kamistoat.meimeichat.meimeichatclient.socket.NettyClient;
import com.kamistoat.meimeichat.meimeichatui.view.chat.ChatController;
import com.kamistoat.meimeichat.meimeichatui.view.chat.IChatMethod;
import com.kamistoat.meimeichat.meimeichatui.view.login.ILoginMethod;
import com.kamistoat.meimeichat.meimeichatui.view.login.LoginController;
import com.kamistoat.meimeichatserveraggrement.protocol.login.ReconnectRequest;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.*;
import java.util.Enumeration;
import java.util.concurrent.*;

public class MeiMeiChatClientApplication extends javafx.application.Application {

    private static final Logger LOGGER = LoggerFactory.getLogger(MeiMeiChatClientApplication.class);

    //默认线程池
    public static ExecutorService executorService = Executors.newFixedThreadPool(8);
    public ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);

    @Override
    public void start(Stage primaryStage) throws Exception {
        System.out.println(getInterIP2());

        // 1. 启动窗口UI中转
        IChatMethod chat = new ChatController(new ChatEvent());
        ILoginMethod login = new LoginController(new LoginEvent(), chat);

        UIServiceConnector uiServiceConnector = new UIServiceConnector();
        uiServiceConnector.setIChatMethod(chat);
        uiServiceConnector.setILoginMethod(login);
        BeanUtil.addBean("uiServiceConnector", uiServiceConnector);

        // 2. 启动socket连接
        LOGGER.info("Netty Client 连接服务器开始 inetHost：{}, inetPort：{}", NettyClientConstant.NETTY_SERVER_CONNECT_HOST, NettyClientConstant.NETTY_SERVER_CONNECT_PORT);
        NettyClient nettyClient = new NettyClient(uiServiceConnector);
        Future<ChannelFuture> nettyChannelFuture = executorService.submit(nettyClient);
        Channel nettyClientChannel = null;
        try {
            nettyClientChannel = nettyChannelFuture.get().channel();
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("Netty Client Start Error");
            throw e;
        }

        // 3. 启动P2P监听
        LOGGER.info("Netty Client P2P 监听开始启动..");
        KcpNettyClient kcpNettyClient = new KcpNettyClient(uiServiceConnector);
        Future<ChannelFuture> kcp_nettyChannelFuture = executorService.submit(kcpNettyClient);
        Channel kcp_nettyClientChannel = null;
        try {
            kcp_nettyClientChannel = kcp_nettyChannelFuture.get().channel();
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("Netty Client P2P Listener Start Error");
            throw e;
        }

        while (!nettyClientChannel.isActive()) {
            LOGGER.info("Netty Client启动服务ing ...");
            Thread.sleep(3000);
        }

        while (!kcp_nettyClientChannel.isActive()) {
            LOGGER.info("Netty Client P2P Listener 启动服务ing ...");
            Thread.sleep(3000);
        }

        LOGGER.info("Netty Client 连接服务器完成... 客户端: {}... 服务端: {}", nettyClientChannel.localAddress(), nettyClientChannel.remoteAddress());
        LOGGER.info("Netty Client P2P Listener 监听启动完成... 监听地址: {}", kcp_nettyClientChannel.localAddress());
        System.out.println(
                "/$$      /$$             /$$     /$$      /$$             /$$   \n" +
                        "| $$$    /$$$            |__/    | $$$    /$$$            |__/  \n" +
                        "| $$$$  /$$$$   /$$$$$$   /$$    | $$$$  /$$$$   /$$$$$$   /$$  \n" +
                        "| $$ $$/$$ $$  /$$__  $$ | $$    | $$ $$/$$ $$  /$$__  $$ | $$  \n" +
                        "| $$  $$$| $$ | $$$$$$$$ | $$    | $$  $$$| $$ | $$$$$$$$ | $$  \n" +
                        "| $$\\  $ | $$ | $$_____/ | $$    | $$\\  $ | $$ | $$_____/ | $$  \n" +
                        "| $$ \\/  | $$ |  $$$$$$$ | $$    | $$ \\/  | $$ |  $$$$$$$ | $$  \n" +
                        "|__/     |__/  \\_______/ |__/    |__/     |__/  \\_______/ |__/ ");

        // 4. 全部成功后拉起窗口
        login.doShow();

//        try{
//            while(true){
//                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//                URIBuilder uriBuilder = new URIBuilder(
//                        NettyClientConstant.NETTY_SERVER_WEB_HOST +
//                                ":" +
//                                NettyClientConstant.NETTY_SERVER_WEB_PORT +
//                                "/meimeichatserver/webapi/test1");
//                HttpGet httpGet = new HttpGet(uriBuilder.build());
//                httpClient.execute(httpGet);
//                Thread.sleep(1000);
//            }
//
//        } catch (URISyntaxException | IOException e) {
//            e.printStackTrace();
//        }

        // Channel状态定时巡检；5秒后每15秒执行一次
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            while (!nettyClient.isActive()) {
                LOGGER.error("通信管道巡检：通信管道状态 " + nettyClient.isActive());
                try {
                    LOGGER.info("通信管道巡检：断线重连[Begin]");
                    ChannelFuture freshChannelFuture = executorService.submit(nettyClient).get();
                    if (null == CacheUtil.userId) {
                        Thread.sleep(3000);
                        continue;
                    }
                    freshChannelFuture.channel().writeAndFlush(new ReconnectRequest(CacheUtil.userId));
                } catch (InterruptedException | ExecutionException e) {
                    System.out.println("通信管道巡检：断线重连[Error]");
                }
            }
        }, 5, 15, TimeUnit.SECONDS);
    }

    public static void main(String[] args) {
        launch(args);
    }

    public String getInterIP2() throws SocketException {
        String localip = null;// 本地IP
        String netip = null;// 外网IP
        Enumeration<NetworkInterface> netInterfaces;
        netInterfaces = NetworkInterface.getNetworkInterfaces();
        InetAddress ip = null;
        boolean finded = false;// 是否找到外网IP
        while (netInterfaces.hasMoreElements() && !finded) {
            NetworkInterface ni = netInterfaces.nextElement();
            Enumeration<InetAddress> address = ni.getInetAddresses();
            while (address.hasMoreElements()) {
                ip = address.nextElement();
                if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
                    // 外网IP
                    netip = ip.getHostAddress();
                    finded = true;
                    break;
                } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
                    // 内网IP
                    localip = ip.getHostAddress();
                }
            }
        }
        if (netip != null && !"".equals(netip)) {
            return netip;
        } else {
            return localip;
        }
    }

}
